#!/usr/bin/env python3
"""
Syscare MCP Server

面向 syscare 热补丁管理工具的命令行操作封装。

MCP tools 列表：
1. syscare_service_control - 控制syscare服务状态（启动/重启/重载）
2. syscare_build_patch - 构建补丁包
3. syscare_build_error_test - 测试构建补丁时的错误参数
4. syscare_patch_management - 管理补丁的全生命周期操作
5. syscare_list_patches - 列出已安装的补丁
6. syscare_patch_info - 查看补丁详细信息

所有工具返回统一的JSON结构：
{
    "success": bool,      # 命令是否成功执行
    "command": str,       # 执行的完整命令
    "exit_code": int,     # 命令退出码
    "stdout": str,        # 标准输出内容
    "stderr": str         # 标准错误内容
}
"""

import subprocess
import json
from typing import List, Optional
from mcp.server.fastmcp import FastMCP, Context

mcp = FastMCP("Syscare MCP Server")

@mcp.tool()
def syscare_service_control(action: str) -> dict:
    """
    控制syscare服务状态
    
    参数:
        action: 服务操作类型，支持 'start', 'restart', 'reload'
    
    返回:
        统一JSON结构，包含命令执行结果
    """
    valid_actions = ['start', 'restart', 'reload']
    if action not in valid_actions:
        return {
            "success": False,
            "command": f"systemctl {action} syscare.service",
            "exit_code": 1,
            "stdout": "",
            "stderr": f"Invalid action: {action}. Supported actions: {valid_actions}"
        }
    
    command = f"systemctl {action} syscare.service"
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
        return {
            "success": result.returncode == 0,
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": "Command timed out"
        }
    except Exception as e:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": str(e)
        }

@mcp.tool()
def syscare_build_patch(
    patch_name: str,
    source: str,
    debuginfo: str,
    patch_file: str,
    patch_arch: Optional[str] = None,
    patch_version: Optional[int] = 1,
    patch_release: Optional[int] = 1,
    patch_description: Optional[str] = "",
    patch_requires: Optional[str] = "",
    build_root: Optional[str] = ".",
    output: Optional[str] = ".",
    jobs: Optional[int] = 2,
    skip_compiler_check: Optional[bool] = False,
    skip_cleanup: Optional[bool] = False,
    verbose: Optional[bool] = False
) -> dict:
    """
    构建补丁包
    
    参数:
        patch_name: 补丁名称
        source: 源码包路径
        debuginfo: debuginfo包路径
        patch_file: 补丁文件路径
        patch_arch: 补丁架构（默认当前架构）
        patch_version: 补丁版本（默认1）
        patch_release: 补丁发布版本（默认1）
        patch_description: 补丁描述
        patch_requires: 补丁依赖
        build_root: 构建根目录（默认当前目录）
        output: 输出目录（默认当前目录）
        jobs: 并行作业数（默认2）
        skip_compiler_check: 跳过编译器检查
        skip_cleanup: 跳过清理
        verbose: 详细输出
    
    返回:
        统一JSON结构，包含命令执行结果
    """
    # 构建基本命令
    cmd_parts = ["syscare", "build"]
    cmd_parts.extend(["--patch-name", patch_name])
    cmd_parts.extend(["--source", source])
    cmd_parts.extend(["--debuginfo", debuginfo])
    cmd_parts.extend(["--patch", patch_file])
    
    # 添加可选参数
    if patch_arch:
        cmd_parts.extend(["--patch-arch", patch_arch])
    if patch_version:
        cmd_parts.extend(["--patch-version", str(patch_version)])
    if patch_release:
        cmd_parts.extend(["--patch-release", str(patch_release)])
    if patch_description:
        cmd_parts.extend(["--patch-description", patch_description])
    if patch_requires:
        cmd_parts.extend(["--patch-requires", patch_requires])
    if build_root:
        cmd_parts.extend(["--build-root", build_root])
    if output:
        cmd_parts.extend(["--output", output])
    if jobs:
        cmd_parts.extend(["--jobs", str(jobs)])
    if skip_compiler_check:
        cmd_parts.append("--skip-compiler-check")
    if skip_cleanup:
        cmd_parts.append("--skip-cleanup")
    if verbose:
        cmd_parts.append("--verbose")
    
    command = " ".join(cmd_parts)
    
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=300)
        return {
            "success": result.returncode == 0,
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": "Command timed out"
        }
    except Exception as e:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": str(e)
        }

@mcp.tool()
def syscare_build_error_test(error_type: str, patch_name: str, source: str, debuginfo: str, patch_file: str) -> dict:
    """
    测试构建补丁时的错误参数情况
    
    参数:
        error_type: 错误类型，支持 'empty_description', 'empty_requires', 'negative_jobs', 
                   'invalid_name', 'missing_source', 'missing_debuginfo'
        patch_name: 补丁名称
        source: 源码包路径
        debuginfo: debuginfo包路径
        patch_file: 补丁文件路径
    
    返回:
        统一JSON结构，包含命令执行结果
    """
    cmd_parts = ["syscare", "build", "--patch-name", patch_name]
    
    if error_type == 'empty_description':
        cmd_parts.extend(["--source", source, "--debuginfo", debuginfo, "--patch", patch_file, "--patch-description"])
    elif error_type == 'empty_requires':
        cmd_parts.extend(["--source", source, "--debuginfo", debuginfo, "--patch", patch_file, "--patch-requires"])
    elif error_type == 'negative_jobs':
        cmd_parts.extend(["--source", source, "--debuginfo", debuginfo, "--patch", patch_file, "--jobs", "-1"])
    elif error_type == 'invalid_name':
        cmd_parts = ["syscare", "build", "--patch-name", "@^<>!$%^&*()+_=-", "--source", source, "--debuginfo", debuginfo, "--patch", patch_file]
    elif error_type == 'missing_source':
        cmd_parts.extend(["--source", "--debuginfo", debuginfo, "--patch", patch_file])
    elif error_type == 'missing_debuginfo':
        cmd_parts.extend(["--source", source, "--debuginfo", "--patch", patch_file])
    else:
        return {
            "success": False,
            "command": "",
            "exit_code": 1,
            "stdout": "",
            "stderr": f"Unknown error type: {error_type}"
        }
    
    command = " ".join(cmd_parts)
    
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=300)
        return {
            "success": result.returncode != 0,  # 对于错误测试，非0退出码表示测试成功
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": "Command timed out"
        }
    except Exception as e:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": str(e)
        }

@mcp.tool()
def syscare_patch_management(patch_name: str, action: str) -> dict:
    """
    管理补丁的全生命周期操作
    
    参数:
        patch_name: 补丁名称
        action: 操作类型，支持 'check', 'apply', 'deactive', 'active', 'remove', 'info', 'accept'
    
    返回:
        统一JSON结构，包含命令执行结果
    """
    valid_actions = ['check', 'apply', 'deactive', 'active', 'remove', 'info', 'accept']
    if action not in valid_actions:
        return {
            "success": False,
            "command": f"syscare {action} {patch_name}",
            "exit_code": 1,
            "stdout": "",
            "stderr": f"Invalid action: {action}. Supported actions: {valid_actions}"
        }
    
    command = f"syscare {action} {patch_name}"
    
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=60)
        return {
            "success": result.returncode == 0,
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": "Command timed out"
        }
    except Exception as e:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": str(e)
        }

@mcp.tool()
def syscare_list_patches() -> dict:
    """
    列出已安装的补丁
    
    返回:
        统一JSON结构，包含命令执行结果
    """
    command = "syscare list"
    
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
        return {
            "success": result.returncode == 0,
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": "Command timed out"
        }
    except Exception as e:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": str(e)
        }

@mcp.tool()
def syscare_patch_info(patch_name: str) -> dict:
    """
    查看补丁详细信息
    
    参数:
        patch_name: 补丁名称
    
    返回:
        统一JSON结构，包含命令执行结果
    """
    command = f"syscare info {patch_name}"
    
    try:
        result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
        return {
            "success": result.returncode == 0,
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": "Command timed out"
        }
    except Exception as e:
        return {
            "success": False,
            "command": command,
            "exit_code": -1,
            "stdout": "",
            "stderr": str(e)
        }

if __name__ == "__main__":
    mcp.run()